#include <iostream>
#include <mutex>
#include <thread>
#include <functional>
#include <vector>
#include <queue>
#include <random>
#include <cstdlib>
#include <deque>
#include<unistd.h>
#include <climits>
#include <chrono>
#include <condition_variable>
#include "Log.hpp"

using namespace ns_log;
using namespace std;

#define default_thread_num 5
// 工作窃取队列类
template <class T>
class WorkStealingQueue
{
private:
    std::deque<T> queue;
    std::mutex _mtx;

public:
    WorkStealingQueue()
    {
    }
    ~WorkStealingQueue()
    {
    }
    WorkStealingQueue(const WorkStealingQueue &other)
    {
        queue = other.queue;
    }
    bool empty()
    {
        std::lock_guard<std::mutex> lock(_mtx);
        return queue.empty();
    }

    bool try_pop(T *value)
    {
        std::lock_guard<std::mutex> lock(_mtx);
        if (queue.empty())
        {
            return false;
        }
        // std::cout << "thread id = " << this_thread::get_id() << "开始执行任务!" << endl;
        *value = queue.front();
        queue.pop_front();
        return true;
    }
    int size()
    {
        return queue.size();
    }
    bool try_steal(T *value)
    {
        std::lock_guard<std::mutex> lock(_mtx);
        if (queue.empty())
        {
            return false;
        }
        // std::cout << "thread id = " << this_thread::get_id() << "开始窃取任务!" << endl;
        *value = queue.back();
        queue.pop_back();
        return true;
    }

    void push(T value)
    {
        std::lock_guard<std::mutex> lock(_mtx);
        queue.push_front(std::move(value));
    }
};

template <class T>
class ThreadPool
{
private:
    // 任务队列
    vector<WorkStealingQueue<T>> _task_queue;
    // 锁
    std::mutex _mtx;
    // 条件变量
    std::condition_variable _con;
    // 管理线程的结构
    std::vector<std::thread> _threads;
    bool _isrunning;
    // 睡眠的线程数量
    int _threadsNums;
    static ThreadPool<T> *_pool;
    static std::mutex _mutex;

private:
    void HandlerTask(int index)
    {
        while (_isrunning)
        {
            T task;
            if (_task_queue[index].try_pop(&task) && _isrunning)
            {
                // 如果有任务就继续执行自己队列中的任务
                task();
            }
            else
            {
                // 如果自己的任务队列没有任务了，就开始窃取!
                int limit = 0;
                while (_task_queue[index].empty() && _isrunning)
                {
                    if (_task_queue[RandNum()].try_steal(&task))   
                    {
                        task();
                    }
                    else 
                    {
                        if(++limit >= 5) 
                        {
                            std::unique_lock<std::mutex> lock(_mtx);
                            _con.wait(lock);
                            limit = 0;
                        }

                    }
                }
            }
        }
    }

public:
    static ThreadPool<T> *GetThreadPoolInstance(int threadnum = default_thread_num)
    {
        // 双重检查锁定模式
        if (_pool == nullptr)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_pool == nullptr)
                _pool = new ThreadPool<T>(threadnum);
        }
        return _pool;
    }
    ThreadPool(int threadnum)
        : _isrunning(true),
          _threadsNums(threadnum)
    {
        _task_queue.resize(threadnum);
        for (int i = 0; i < _threadsNums; i++)
        {
            // LOG(DEBUG, "Load thread-[%d] to vector done!\n", i);
            _threads.emplace_back(std::bind(&ThreadPool::HandlerTask, this, i));
        }
    }
    // 向任务队列插入任务
    void Push(const T &task)
    {
        _task_queue[Distribution()].push(task);
        // 有任务立即通知消费者
        _con.notify_one();
    }
    int RandNum()
    {
        return rand() % _threadsNums;
    }
    int Distribution()
    {
        std::lock_guard<std::mutex> lock(_mtx);
        int ret = INT_MAX;
        int index = 0;
        for (int i = 0;i<_task_queue.size();i++)
        {
            if(ret > _task_queue[i].size())
            {
                index = i;
                ret = _task_queue[i].size();
            }
        }
        return index;
    }
    // 停止线程池
    void Stop()
    {
        std::unique_lock<std::mutex> lock(_mtx);
        _isrunning = false;
        _con.notify_all();
    }
    ~ThreadPool()
    {
        for (auto &thread : _threads)
        {
            LOG(DEBUG, "thread join done!\n");
            thread.join();
        }
    }
};

// 类外初始化
template <class T>
ThreadPool<T> *ThreadPool<T>::_pool = nullptr;
template <class T>
std::mutex ThreadPool<T>::_mutex;

using func_t = std::function<void()>;
int main()
{
    std::mutex mtx;
    srand(time(nullptr));
    func_t task = []()
    {
        int i = 0;
        while(i <= 10) ++i;
    };
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 1000000; i++)
    {
        ThreadPool<func_t>::GetThreadPoolInstance()->Push(task);
    }
    auto end = std::chrono::high_resolution_clock::now();
     // 计算时间差（毫秒）
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    {
        unique_lock<std::mutex> lock(mtx);
        std::cout << "代码执行时间：" << duration << " 毫秒" << std::endl;
    }
    ThreadPool<func_t>::GetThreadPoolInstance()->Stop();
}